/*
 * StickChart.java
 * Android-Charts
 *
 * Created by limc on 2011/05/29.
 *
 * Copyright 2011 limc.cn All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.limc.ohoscharts.view;


import cn.limc.ohoscharts.entity.IChartData;
import cn.limc.ohoscharts.entity.IMeasurable;
import cn.limc.ohoscharts.entity.IStickEntity;
import cn.limc.ohoscharts.event.*;
import cn.limc.ohoscharts.axis.IAxis;
import cn.limc.ohoscharts.mole.IMole;
import cn.limc.ohoscharts.mole.IMoleProvider;
import cn.limc.ohoscharts.mole.StickMole;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

/**
 * <p>
 * StickChart is a kind of graph that draw the sticks on a GridChart if you want
 * display some moving average lines on this graph, please use see MAStickChart
 * for more information.
 * </p>
 * <p>
 * StickChartはGridChartの表面でスティックを書いたラインチャードです。移動平均線など
 * 分析線がお使いしたい場合、MAStickChartにご参照ください。
 * </p>
 * <p>
 * StickChart是在GridChart上绘制柱状数据的图表、如果需要支持显示均线，请参照 MAStickChart。
 * </p>
 *
 * @author limc
 * @version v1.0 2011/05/30 14:58:59
 */
public class StickChart extends PeriodDataGridChart implements IZoomable,
		Component.TouchEventListener {

  protected IMoleProvider provider = new IMoleProvider() {
    public IMole getMole() {
      return new StickMole() {
        @Override
        public void setPro() {
          stickFillColor = Color.BLUE.getValue();
          stickBorderColor = Color.WHITE.getValue();
          stickStrokeWidth = 1;
          stickSpacing = 1;
        }
      };
    }
  };

  public static final int DEFAULT_STICK_SPACING = 1;


  /**
   * <p>
   * max number of sticks
   * </p>
   * <p>
   * スティックの最大表示数
   * </p>
   * <p>
   * 柱条的最大表示数
   * </p>
   */
  protected int maxSticksNum;

  protected int minDisplayNum = MINI_DISPLAY_NUM;

  protected int stickSpacing = DEFAULT_STICK_SPACING;

  protected OnZoomGestureListener onZoomGestureListener = new OnZoomGestureListener();
  protected IGestureDetector zoomGestureDetector = new ZoomGestureDetector<IZoomable>(this);

  protected IDisplayCursorListener onDisplayCursorListener;

  /*
   * (non-Javadoc)
   *
   * @param context
   *
   * @see cn.limc.ohoscharts.view.AbstractBaseChart#BaseChart(Context)
   */
  public StickChart(Context context) {
    super(context);
  }

  /*
   * (non-Javadoc)
   *
   * @param context
   *
   * @param attrs
   *
   * @param defStyle
   *
   * @see cn.limc.ohoscharts.view.AbstractBaseChart#BaseChart(Context,
   * AttributeSet, int)
   */
  public StickChart(Context context, AttrSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  /*
   * (non-Javadoc)
   *
   * @param context
   *
   * @param attrs
   *
   * @see cn.limc.ohoscharts.view.AbstractBaseChart#BaseChart(Context,
   * AttributeSet)
   */
  public StickChart(Context context, AttrSet attrs) {
    super(context, attrs);
  }

  /*
   * (non-Javadoc)
   *
   * <p>Called when is going to draw this chart<p> <p>チャートを書く前、メソッドを呼ぶ<p>
   * <p>绘制图表时调用<p>
   *
   * @param canvas
   *
   * @see ohos.view.View#onDraw(ohos.graphics.Canvas)
   */

  @Override
  public void onDraw(Component component, Canvas canvas) {
    super.onDraw(component, canvas);
    if (this.autoCalcValueRange) {
      calcValueRange();
    }
    initAxisY(canvas);
    initAxisX(canvas);
    //super.onDraw(canvas);
    drawSticks(canvas);
  }


  /**
   * <p>
   * draw sticks
   * </p>
   * <p>
   * スティックを書く
   * </p>
   * <p>
   * 绘制柱条
   * </p>
   *
   * @param canvas
   */
  protected void drawSticks(Canvas canvas) {
    if (null == stickData) {
      return;
    }
    if (stickData.size() <= 0) {
      return;
    }

    float stickWidth = dataQuadrant.getPaddingWidth() / getDisplayNumber();

    if (axisY.getPosition() == IAxis.AXIS_Y_POSITION_LEFT) {

      float stickX = dataQuadrant.getPaddingStartX();

      for (int i = 0; i < stickData.size(); i++) {
        IMeasurable stick = stickData.get(i);
        StickMole mole = (StickMole) provider.getMole();
        mole.setUp(this, stick, stickX, stickWidth);
        mole.draw(canvas);
        // next x
        stickX = stickX + stickWidth;
      }
    } else {
      float stickX = dataQuadrant.getPaddingEndX() - stickWidth;
      for (int i = stickData.size() - 1; i >= 0; i--) {
        IMeasurable stick = stickData.get(i);
        StickMole mole = (StickMole) provider.getMole();
        mole.setUp(this, stick, stickX, stickWidth);
        mole.draw(canvas);
        // next x
        stickX = stickX - stickWidth;
      }
    }

  }

//	private float olddistance;
//	private float newdistance;

  /*
   * (non-Javadoc)
   *
   * <p>Called when chart is touched<p> <p>チャートをタッチしたら、メソッドを呼ぶ<p>
   * <p>图表点击时调用<p>
   *
   * @param event
   *
   * @see ohos.view.View#onTouchEvent(MotionEvent)
   */


  @Override
  public boolean onTouchEvent(Component component, TouchEvent event) {
    super.onTouchEvent(component, event);
    MmiPoint point = event.getPointerPosition(event.getIndex());
    //valid
    if (!isValidTouchPoint(point.getX(), point.getY())) {
      return false;
    }
    if (null == stickData || stickData.size() == 0) {
      return false;
    }
    zoomGestureDetector.onTouchEvent(event);
    return true;
  }


  /**
   * <p>
   * Zoom in the graph
   * </p>
   * <p>
   * 拡大表示する。
   * </p>
   * <p>
   * 放大表示
   * </p>
   */
  public void zoomIn() {
    if (getDisplayNumber() > getMinDisplayNumber()) {
      setDisplayNumber(getDisplayNumber() - ZOOM_STEP);
      this.invalidate();
    }

    //Listener
    if (onDisplayCursorListener != null) {
      onDisplayCursorListener.onCursorChanged(this, getDisplayFrom(), getDisplayNumber());
    }
  }

  /**
   * <p>
   * Zoom out the grid
   * </p>
   * <p>
   * 縮小表示する。
   * </p>
   * <p>
   * 缩小
   * </p>
   */
  public void zoomOut() {
    if (getDisplayNumber() < stickData.size() - 1 - ZOOM_STEP) {
      setDisplayNumber(getDisplayNumber() + ZOOM_STEP);
      this.invalidate();
    }

    //Listener
    if (onDisplayCursorListener != null) {
      onDisplayCursorListener.onCursorChanged(this, getDisplayFrom(), getDisplayNumber());
    }
  }

  /**
   * @return the stickData
   */
  public IChartData<IStickEntity> getStickData() {
    return stickData;
  }

  /**
   * @param stickData the stickData to set
   */
  public void setStickData(IChartData<IStickEntity> stickData) {
    this.stickData = stickData;
  }

  /**
   * @return the maxSticksNum
   */
  @Deprecated
  public int getMaxSticksNum() {
    return maxSticksNum;
  }

  /**
   * @param maxSticksNum the maxSticksNum to set
   */
  @Deprecated
  public void setMaxSticksNum(int maxSticksNum) {
    this.maxSticksNum = maxSticksNum;
  }

  /**
   * @return the stickSpacing
   */
  public int getStickSpacing() {
    return stickSpacing;
  }

  /**
   * @param stickSpacing the stickSpacing to set
   */
  public void setStickSpacing(int stickSpacing) {
    this.stickSpacing = stickSpacing;
  }

  /* (non-Javadoc)
   *
   * @return
   * @see cn.limc.ohoscharts.common.IDataCursor#displayFrom()
   */
  public int getDisplayFrom() {
    if (axisY.getPosition() == IAxis.AXIS_Y_POSITION_LEFT) {
      return 0;
    } else {
      return stickData.size() - maxSticksNum;
    }
  }

  /* (non-Javadoc)
   *
   * @return
   * @see cn.limc.ohoscharts.common.IDataCursor#displayNumber()
   */
  public int getDisplayNumber() {
    return maxSticksNum;
  }

  /* (non-Javadoc)
   *
   * @return
   * @see cn.limc.ohoscharts.common.IDataCursor#displayTo()
   */
  public int getDisplayTo() {
    if (axisY.getPosition() == IAxis.AXIS_Y_POSITION_LEFT) {
      return maxSticksNum;
    } else {
      return stickData.size() - 1;
    }
  }

  /* (non-Javadoc)
   *
   * @param displayFrom
   * @see cn.limc.ohoscharts.common.IDataCursor#setDisplayFrom(int)
   */
  public void setDisplayFrom(int displayFrom) {
    //TODO
  }

  /* (non-Javadoc)
   *
   * @param displayNumber
   * @see cn.limc.ohoscharts.common.IDataCursor#setDisplayNumber(int)
   */
  public void setDisplayNumber(int displayNumber) {
    maxSticksNum = displayNumber;
  }

  /* (non-Javadoc)
   *
   * @param displayTo
   * @see cn.limc.ohoscharts.common.IDataCursor#setDisplayTo(int)
   */
  public void setDisplayTo(int displayTo) {
    //TODO
  }

  /* (non-Javadoc)
   *
   * @return
   * @see cn.limc.ohoscharts.common.IDataCursor#getMinDisplayNumber()
   */
  public int getMinDisplayNumber() {
    return minDisplayNum;
  }

  /* (non-Javadoc)
   *
   * @param minDisplayNumber
   * @see cn.limc.ohoscharts.common.IDataCursor#getMinDisplayNumber(int)
   */
  public void setMinDisplayNumber(int minDisplayNumber) {
    this.minDisplayNum = minDisplayNumber;
  }

  /* (non-Javadoc)
   *
   * @return
   * @see cn.limc.ohoscharts.event.IZoomable#getOnZoomGestureListener()
   */
  public OnZoomGestureListener getOnZoomGestureListener() {
    return onZoomGestureListener;
  }

  /* (non-Javadoc)
   *
   * @param listener
   * @see cn.limc.ohoscharts.event.IZoomable#setOnZoomGestureListener(cn.limc.ohoscharts
   * .event.OnZoomGestureListener)
   */
  public void setOnZoomGestureListener(OnZoomGestureListener listener) {
    this.onZoomGestureListener = listener;
  }

  /**
   * @return the onDisplayCursorListener
   */
  public IDisplayCursorListener getOnDisplayCursorListener() {
    return onDisplayCursorListener;
  }

  /**
   * @param onDisplayCursorListener the onDisplayCursorListener to set
   */
  public void setOnDisplayCursorListener(
      IDisplayCursorListener onDisplayCursorListener) {
    this.onDisplayCursorListener = onDisplayCursorListener;
  }
}
